package com.xiyuan.smartutils.control;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.logging.LogFactory;
import com.xiyuan.smartutils.logging.Logger;

import java.util.*;

/**
 * 事件处理线程池控制器，指定池最小值、最大值、初始值，允许线程空闲时长和允许缓存对象大小<br>
 * <br>
 * 1.创建时创建初始值大小的线程池，创建对象队列，和主线程<br>
 * 2.其他线程通过post传递对象可执行对象<br>
 * 3.主线程调度线程池处理对象，并检查线程池空闲线程
 * 4.每个事件支持多个事件处理器处理，其中某个事件处理器return=false表示终止事件处理,return=true表示继续处理
 *
 * @version v1.0.0 @author lgz 2017-8-27 新建与整理
 */
public class EventController extends ThreaderController {
    private static final Logger log = LogFactory.getLogger(EventController.class);
    private final Map<Class<?>, List<Eventor<?>>> eventerMap = new HashMap<Class<?>, List<Eventor<?>>>();
    
    public EventController() {
        setDaemon(true);
        setThreadName(newName("Eventor-"));
    }
    
    @Override
    public void closeAfter() {
        super.closeAfter();
        eventerMap.clear();
    }
    
    /**
     * 增加一个对象处理器
     */
    public void addEventer(Eventor<?> eventer) {
        Class<?> clazz = eventer.clazz();
        List<Eventor<?>> list = eventerMap.get(clazz);
        if (list == null) {
            list = new ArrayList<Eventor<?>>();
            eventerMap.put(clazz, list);
        }
        
        list.add(eventer);
    }
    
    /**
     * 删除一个对象处理器
     */
    public void removeEventer(Eventor<?> eventer) {
        Class<?> clazz = eventer.clazz();
        List<Eventor<?>> list = eventerMap.get(clazz);
        if (list == null) {return;}
        
        for (Iterator<Eventor<?>> it = list.iterator(); it.hasNext(); ) {
            Eventor<?> item = it.next();
            if (item.getClass() == eventer.getClass()) {it.remove();}
        }
        
        // 如果删除后没有，则删除事件处理索引，认为该事件以后由缺省处理
        if (list.isEmpty()) {eventerMap.remove(clazz);}
    }
    
    /**
     * 处理一个对象，转化为HandlerRunnable由父类处理
     */
    public boolean execute(Object event) {
        return execute(event, false);
    }
    
    /**
     * 处理一个对象，转化为HandlerRunnable由父类处理
     */
    public boolean execute(Object event, boolean priority) {
        List<Eventor<?>> eventer = eventerMap.get(event.getClass());
        if (eventer == null) {
            log.error(StrUtils.format("事件处理器[%s]未配置处理器", event.getClass().getName()));
            return false;
        }
        
        @SuppressWarnings({"rawtypes", "unchecked"})
        Eventee<?> command = new Eventee(event, eventer);
        return super.execute(command, priority);
    }
}
